import { BaseService } from '@/core/base.service';
import { TokenLogQueryDto } from '@/dtos';
import { Injectable } from '@nestjs/common';
import { Prisma, TokenLog } from '@prisma/client';

@Injectable()
export class TokenLogService extends BaseService {
  async query({ params, sort }: TokenLogQueryDto) {
    const { current = 1, pageSize = 20, keyword, ...where } = params;

    let sql = `
      SELECT #{fields} FROM TokenLog AS t
      LEFT JOIN Token AS tt ON tt.id = t.tokenId
      LEFT JOIN Asset AS a ON a.id = tt.assetId
      LEFT JOIN User AS o ON tt.ownerId = o.id
      LEFT JOIN User AS f ON t.fromId = f.id
      LEFT JOIN User AS r ON t.recipientId = r.id            
      WHERE t.type not in (6, 7)
      AND t.isDeleted = false
        ${!!where.type ? `AND t.type = ${where.type}` : ''}
        ${!!where.title ? `AND a.title LIKE '%${where.title}%'` : ''}
        ${!!where.fromName ? `AND f.realname LIKE '%${where.fromName}%'` : ''}
        ${!!where.fromMobile ? `AND f.mobile LIKE '%${where.fromMobile}%'` : ''}
        ${!!where.recipientName ? `AND r.realname LIKE '%${where.recipientName}%'` : ''}
        ${!!where.recipientMobile ? `AND r.mobile LIKE '%${where.recipientMobile}%'` : ''}
        ${!!where.no ? `AND tt.no = ${where.no}` : ''}
    `;

    const [{ count }] = await this.prisma.$queryRawUnsafe<[{ count: number }]>(
      sql.replace('#{fields}', 'COUNT(t.id) AS count'),
    );

    const list = await this.prisma.$queryRawUnsafe<TokenLog[]>(
      `${sql.replace(
        '#{fields}',
        `
        t.id, t.log, t.type, t.createdAt,
        tt.no, tt.assetId, a.title,
        o.mobile AS ownerMobile, o.realname AS ownerName,
        f.mobile AS fromMobile, f.realname AS fromName,
        r.mobile AS recipientMobile, r.realname AS recipientName
      `,
      )}
      ORDER BY ${
        !!sort && Object.keys(sort).length > 0
          ? Object.entries(sort)
              .map(([k, v]) => `t.${k} ${v === 'descend' ? 'DESC' : 'ASC'}`)
              .join(',')
          : 't.id DESC'
      }
      LIMIT ${pageSize} 
      OFFSET ${(current - 1) * pageSize}
      `,
    );

    const total = count ? Number(count) : 0;
    const totalPage = Math.ceil(total / pageSize);
    const hasMore = current < totalPage;

    return {
      total,
      totalPage,
      hasMore,
      current,
      pageSize,
      list,
    };
  }

  async findOne(
    where: Prisma.TokenLogWhereUniqueInput,
    select?: Prisma.TokenLogSelect,
  ): Promise<TokenLog | null> {
    return this.prisma.tokenLog.findUnique({
      where,
      select,
    });
  }

  async create(data: Prisma.TokenLogCreateInput): Promise<TokenLog> {
    return this.prisma.tokenLog.create({
      data,
    });
  }

  async update(params: {
    where: Prisma.TokenLogWhereUniqueInput;
    data: Prisma.TokenLogUpdateInput;
  }): Promise<TokenLog> {
    const { where, data } = params;
    return this.prisma.tokenLog.update({
      where,
      data,
    });
  }

  async remove(where: Prisma.TokenLogWhereUniqueInput): Promise<TokenLog> {
    return this.prisma.tokenLog.update({
      where,
      data: {
        isDeleted: true,
      },
    });
  }
}
